import { S3Client, PutObjectCommand, ListObjectsV2Command, DeleteObjectCommand, HeadBucketCommand, HeadObjectCommand } from '@aws-sdk/client-s3';
import { Upload } from '@aws-sdk/lib-storage';
import * as fs from 'fs-extra';
import { CloudServiceInterface, FileInfo, CloudConfig } from '../types';
import { Logger } from '../../utils/Logger';

export class AWSCloudService implements CloudServiceInterface {
  private s3Client: S3Client;
  private config: CloudConfig;

  constructor(config: CloudConfig) {
    this.config = config;
    this.s3Client = new S3Client({
      region: config.region,
      credentials: {
        accessKeyId: config.accessKeyId,
        secretAccessKey: config.secretAccessKey
      },
      endpoint: config.endpoint
    });
  }

  /**
   * 上传文件
   */
  async uploadFile(
    filePath: string,
    remotePath: string,
    onProgress?: (progress: number) => void
  ): Promise<boolean> {
    try {
      const fileStream = fs.createReadStream(filePath);
      const stat = fs.statSync(filePath);
      
      const upload = new Upload({
        client: this.s3Client,
        params: {
          Bucket: this.config.bucket,
          Key: remotePath,
          Body: fileStream,
          ContentLength: stat.size
        }
      });
      
      // 监听上传进度
      upload.on('httpUploadProgress', (progress) => {
        if (onProgress && progress.loaded && progress.total) {
          const progressPercent = (progress.loaded / progress.total) * 100;
          onProgress(progressPercent);
        }
      });
      
      const result = await upload.done();
      Logger.info('AWS S3上传成功:', result);
      return true;
    } catch (error) {
      console.error('AWS S3上传失败:', error);
      throw error;
    }
  }

  /**
   * 列出文件
   */
  async listFiles(remotePath: string): Promise<FileInfo[]> {
    try {
      const files: FileInfo[] = [];
      let continuationToken: string | undefined;
      
      do {
        const command = new ListObjectsV2Command({
          Bucket: this.config.bucket,
          Prefix: remotePath,
          MaxKeys: 1000,
          ContinuationToken: continuationToken
        });
        
        const result = await this.s3Client.send(command);
        
        if (result.Contents) {
          result.Contents.forEach(item => {
            if (item.Key && item.Size !== undefined && item.LastModified && item.ETag) {
              files.push({
                key: item.Key,
                size: item.Size,
                lastModified: item.LastModified,
                etag: item.ETag.replace(/"/g, '')
              });
            }
          });
        }
        
        continuationToken = result.NextContinuationToken;
      } while (continuationToken);
      
      return files;
    } catch (error) {
      console.error('AWS S3列出文件失败:', error);
      throw error;
    }
  }

  /**
   * 删除文件
   */
  async deleteFile(remotePath: string): Promise<boolean> {
    try {
      const command = new DeleteObjectCommand({
        Bucket: this.config.bucket,
        Key: remotePath
      });
      
      const result = await this.s3Client.send(command);
      Logger.info('AWS S3删除文件成功:', result);
      return true;
    } catch (error) {
      console.error('AWS S3删除文件失败:', error);
      throw error;
    }
  }

  /**
   * 测试连接
   */
  async testConnection(): Promise<boolean> {
    try {
      const command = new HeadBucketCommand({
        Bucket: this.config.bucket
      });
      
      const result = await this.s3Client.send(command);
      Logger.info('AWS S3连接测试成功:', result);
      return true;
    } catch (error) {
      console.error('AWS S3连接测试失败:', error);
      return false;
    }
  }

  /**
   * 获取文件URL
   */
  getFileUrl(remotePath: string): string {
    // AWS S3的公共读取URL格式
    const endpoint = this.config.endpoint || `https://s3.${this.config.region}.amazonaws.com`;
    return `${endpoint}/${this.config.bucket}/${remotePath}`;
  }

  /**
   * 检查文件是否存在
   */
  async fileExists(remotePath: string): Promise<boolean> {
    try {
      const command = new HeadObjectCommand({
        Bucket: this.config.bucket,
        Key: remotePath
      });
      
      await this.s3Client.send(command);
      return true;
    } catch (error: any) {
      if (error.name === 'NotFound' || error.$metadata?.httpStatusCode === 404) {
        return false;
      }
      throw error;
    }
  }

  /**
   * 批量删除文件
   */
  async deleteMultipleFiles(remotePaths: string[]): Promise<boolean> {
    try {
      const deleteParams = {
        Bucket: this.config.bucket,
        Delete: {
          Objects: remotePaths.map(path => ({ Key: path })),
          Quiet: false
        }
      };
      
      // AWS SDK v3中批量删除需要使用DeleteObjectsCommand
      // 这里简化实现，逐个删除
      const deletePromises = remotePaths.map(path => this.deleteFile(path));
      await Promise.all(deletePromises);
      
      return true;
    } catch (error) {
      console.error('AWS S3批量删除文件失败:', error);
      return false;
    }
  }

  /**
   * 获取文件元数据
   */
  async getFileMetadata(remotePath: string): Promise<any> {
    try {
      const command = new HeadObjectCommand({
        Bucket: this.config.bucket,
        Key: remotePath
      });
      
      const result = await this.s3Client.send(command);
      return result;
    } catch (error) {
      console.error('获取文件元数据失败:', error);
      throw error;
    }
  }
}